local M = {}

spine = require "lib.spine.spine"  -- spine 需要全局声明

local configBasePath = "images/spine/"
local imgBasePath = "images/spine/"

--[[
	spineName spine的名字
	animName 要播放的动画名称
	skinName  皮肤名称
	timeScale 时间缩放 不能为0
]]
function M.new(params)
	local gSpine = display.newGroup()
	local path = params.path or ""
	local spineName = params.spineName
	local animName = params.animName or "animation"
	local skinName = params.skinName
	local isLoop = params.isLoop
	local timeScale = params.timeScale or 5

	local imgPath = imgBasePath .. spineName .. ".png"
	local atlasPath = configBasePath .. spineName .. ".atlas"
	local jsonPath = configBasePath .. spineName .. ".json"

	local imageLoader = function(path)
		local paint = {type = "image", filename = imgPath}
		return paint
	end

	local atlas = spine.TextureAtlas.new(spine.utils.readFile(atlasPath), imageLoader)
	local json = spine.SkeletonJson.new(spine.AtlasAttachmentLoader.new(atlas))
	local skeletonData = json:readSkeletonDataFile(jsonPath)
	local skeleton = spine.Skeleton.new(skeletonData)
	skeleton.flipY = true
	skeleton.group.x = x
	skeleton.group.y = y
	gSpine:insert(skeleton.group)

	local topGroup = display.newGroup()
	gSpine:insert(topGroup)
	gSpine.topGroup = topGroup

	local animationStateData = spine.AnimationStateData.new(skeletonData)
	animationStateData.defaultMix = 0 -- 动画混合可能会导致动画过渡出现未预期行为，除非过渡很自然，否则不要使用这个参数
	local animationState = spine.AnimationState.new(animationStateData)

	skeleton.group.name = jsonFile

	-- 添加自定义回调函数
	animationState.customEvent = {}

	-- 回调
	animationState.onStart = function (entry)
		-- animationState.customEvent.onStart
		-- print(entry.trackIndex.." start: "..entry.animation.name)
	end

	animationState.onInterrupt = function (entry)
		-- print(entry.trackIndex.." interrupt: "..entry.animation.name)
	end

	animationState.onEnd = function (entry)
		-- print(entry.trackIndex.." end: "..entry.animation.name)
	end

	animationState.onComplete = function (entry)
		loger.log("onComplete", entry.animation.name)
		if animationState.customEvent[entry.animation.name] and animationState.customEvent[entry.animation.name].onComplete then
			animationState.customEvent[entry.animation.name].onComplete()
		end
		-- print(entry.trackIndex.." complete: "..entry.animation.name)
	end

	animationState.onDispose = function (entry)
		-- print(entry.trackIndex.." dispose: "..entry.animation.name)
	end
	
	animationState.onEvent = function (entry, event)
		-- print(entry.trackIndex.." event: "..entry.animation.name..", "..event.data.name..", "..event.intValue..", "..event.floatValue..", '"..(event.stringValue or "").."'")
	end

	if params.onComplete then
		animationState.customEvent[animName] = animationState.customEvent[animName] or {}
		animationState.customEvent[animName].onComplete = params.onComplete
	end

	-- 判定某个动画是否存在
	function gSpine:isAnimExist(animName)
		return animationState:isAnimExist(animName)
	end

	function gSpine:setTimeScale(scale)
		timeScale = scale
	end

	function gSpine:removeCustomEvent(params)
		local animName = params.animName
		local stausName = params.stausName
	end

	function gSpine:getTopGroup()
		return gSpine.topGroup
	end

	-- 设置皮肤
	function gSpine:setSkin(params)
		local skinName = params.skinName
		skeleton:setSkin(skin)
	end

	-- 设置动画
	function gSpine:setAnimation(params)
		local animName = params.animName
		local trackIndex = params.trackIndex or 0
		local isLoop = not (params.isLoop == false)
		local onComplete = params.onComplete

		animationState.nowAnimName = animName

		if onComplete then
			animationState.customEvent[animName] = animationState.customEvent[animName] or {}
			animationState.customEvent[animName].onComplete = onComplete
		end

		
		animationState:setAnimationByName(trackIndex, animName, isLoop)
	end

	-- 带延迟的添加动画
	function gSpine:addAnimation(params)
		local animName = params.animName
		local trackIndex = params.trackIndex or 0
		local isLoop = not (params.isLoop == false)
		local delay = params.delay or 0

		local mixTime = params.mixTime -- 暂时不要使用这个参数 似乎不太好用

		if mixTime then
			animationStateData:setMix(animationState.nowAnimName, animName, mixTime)
		end

		if params.onComplete then
			animationState.customEvent[animName] = animationState.customEvent[animName] or {}
			animationState.customEvent[animName].onComplete = params.onComplete
		end

		animationState:addAnimationByName(trackIndex, animName, isLoop, delay)
		animationState.nowAnimName = animName
	end

	-- 播放
	function gSpine:play(params)
		local lastTime = 0
		local count = 0

		local function spineRunTime(event)
			if not disLib.isGroup(gSpine) and gSpine.stop then
				gSpine:stop(true)
				return
			end

			count = count + 1
			if count == 1 then
				lastTime = event.time/1000/timeScale
			end
			local currentTime = event.time/1000/timeScale
			local delta = currentTime - lastTime
			lastTime = currentTime

			animationState:update(delta)
			animationState:apply(skeleton)
			skeleton:updateWorldTransform()

			if disLib.isGroup(gSpine) then
				gSpine.topGroup.y = skeleton.group.y - skeleton.group.height
			end
		end

		gSpine.spineRunTime = spineRunTime
		Runtime:addEventListener("enterFrame", gSpine.spineRunTime)
	end

	function gSpine:stop(isRemove)
		Runtime:removeEventListener("enterFrame", gSpine.spineRunTime)
		if isRemove then
			disLib.remove(gSpine)
			gSpine = nil
		end
	end

	gSpine:setAnimation({
		animName = animName,
		isLoop = isLoop
	})

	if skin then
		skeleton.group:setSkin({skinName  = skin})
	end

	return gSpine
end

return M